home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 October / Macworld (1998-10).dmg / Shareware World / Info / For Developers / MacZoop 1.8.4 / More Classes / File Classes / ZResourceFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-08  |  12.1 KB  |  529 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"         
  5. *
  6. *
  7. *
  8. *            ZResourceFile.cpp    -- a generic resource file/manager object
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1997, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21. #include    "ZResourceFile.h"
  22. #include    "MacZoop.h"
  23.  
  24. static FSSpec    gDummySpec = { 0, 0, "\p" };
  25.  
  26. /*-----------------------------***  CONSTRUCTORS  ***----------------------------------*/
  27.  
  28. ZResourceFile::ZResourceFile( const FSSpec& aSpec )
  29.     : ZFile( aSpec )
  30. {
  31. }
  32.  
  33.  
  34. ZResourceFile::ZResourceFile( Str255 fName )
  35.     : ZFile( fName )
  36. {
  37. }
  38.  
  39.  
  40. ZResourceFile::ZResourceFile( const short aRefNum )
  41.     : ZFile( gDummySpec )
  42. {
  43.     // if the file was opened externally (for example, applications are opened
  44.     // by the process manager) you can construct this object with this constructor
  45.     // to obtain a nice object interface to the resources anyway.
  46.     
  47.     resRefNum = aRefNum;
  48. }
  49.  
  50.  
  51. /*-----------------------------***  READRESOURCE  ***----------------------------------*/
  52. /*
  53. get a resource with the type and ID passed, optionally detaching it
  54. ---------------------------------------------------------------------------------------*/
  55.  
  56. Handle        ZResourceFile::ReadResource( const ResType aType, const short resID, const Boolean detachIt)
  57. {
  58.     Handle    h = NULL;
  59.     short    saveRes;
  60.     
  61.     FailOSErr((resRefNum == _NOT_OPEN)? resFNotFound : noErr );
  62.     SetResFork( &saveRes );
  63.     
  64.     try
  65.     {
  66.         h = Get1Resource( aType, resID );
  67.         FailOSErr( ResError());
  68.         
  69.         if ( detachIt )
  70.             DetachResource( h );
  71.     }
  72.     catch( OSErr err )
  73.     {
  74.         UseResFile( saveRes );
  75.         
  76.         throw err;
  77.     }
  78.     
  79.     UseResFile( saveRes );
  80.     
  81.     return h;
  82. }
  83.  
  84.  
  85. /*-----------------------------***  READRESOURCE  ***----------------------------------*/
  86. /*
  87. get an indexed resource with the type and index passed, optionally detaching it
  88. ---------------------------------------------------------------------------------------*/
  89.  
  90. Handle        ZResourceFile::ReadResource( const short index, const ResType aType, const Boolean detachIt)
  91. {
  92.     Handle    h = NULL;
  93.     short    saveRes;
  94.     
  95.     FailOSErr((resRefNum == _NOT_OPEN)? resFNotFound : noErr );
  96.     SetResFork( &saveRes );
  97.     
  98.     try
  99.     {
  100.         h = Get1IndResource( aType, index );
  101.         FailOSErr( ResError());
  102.         
  103.         if ( detachIt )
  104.             DetachResource( h );
  105.     }
  106.     catch( OSErr err )
  107.     {
  108.         UseResFile( saveRes );
  109.         
  110.         throw err;
  111.     }
  112.     
  113.     UseResFile( saveRes );
  114.     
  115.     return h;
  116. }
  117.  
  118.  
  119. /*-----------------------------***  READRESOURCE  ***----------------------------------*/
  120. /*
  121. get a resource with the type and name passed, optionally detaching it
  122. ---------------------------------------------------------------------------------------*/
  123.  
  124. Handle        ZResourceFile::ReadResource( const ResType aType, Str255 resName, const Boolean detachIt)
  125. {
  126.     Handle    h = NULL;
  127.     short    saveRes;
  128.     
  129.     FailOSErr((resRefNum == _NOT_OPEN)? resFNotFound : noErr );
  130.     SetResFork( &saveRes );
  131.     
  132.     try
  133.     {
  134.         h = Get1NamedResource( aType, resName );
  135.         FailOSErr( ResError());
  136.         
  137.         if ( detachIt )
  138.             DetachResource( h );
  139.     }
  140.     catch( OSErr err )
  141.     {
  142.         UseResFile( saveRes );
  143.         
  144.         throw err;
  145.     }
  146.     
  147.     UseResFile( saveRes );
  148.     
  149.     return h;
  150. }
  151.  
  152.  
  153. /*-----------------------------***  OWNSRESOURCE  ***----------------------------------*/
  154. /*
  155. does this resource handle belong to this file? (FALSE if not a resource handle)
  156. ---------------------------------------------------------------------------------------*/
  157.  
  158. Boolean        ZResourceFile::OwnsResource( Handle aResHandle )
  159. {
  160.     short    hf;
  161.     
  162.     FailOSErr((aResHandle == NULL)? paramErr : noErr );
  163.     hf = HomeResFile( aResHandle );
  164.     
  165.     if ((hf == -1) ||
  166.         (hf != resRefNum))
  167.         return FALSE;
  168.     else
  169.         return TRUE;
  170. }
  171.  
  172.  
  173. /*------------------------------***  HASRESOURCE  ***----------------------------------*/
  174. /*
  175. does this file contain a resource of the type and ID passed?
  176. ---------------------------------------------------------------------------------------*/
  177.  
  178. Boolean        ZResourceFile::HasResource( const ResType aType, const short resID )
  179. {
  180.     Handle    h;
  181.     Boolean    result = FALSE;
  182.     
  183.     SetResLoad( FALSE );
  184.     
  185.     try
  186.     {
  187.         h = GetResource( aType, resID );
  188.         
  189.         if( h )
  190.             result = TRUE;
  191.     }
  192.     catch( OSErr err )
  193.     {
  194.         // do not throw this exception (return false instead)
  195.     }
  196.     
  197.     SetResLoad( TRUE );
  198.     
  199.     return result;
  200. }
  201.  
  202.  
  203. /*-------------------------------***  HASRESTYPE  ***----------------------------------*/
  204. /*
  205. does the file contain any resources of the type passed?
  206. ---------------------------------------------------------------------------------------*/
  207.  
  208. Boolean        ZResourceFile::HasResType( const ResType aType )
  209. {
  210.     Boolean        result = FALSE;
  211.     
  212.     try
  213.     {
  214.         result = ( CountResources( aType ) > 0);
  215.     }
  216.     catch( OSErr err )
  217.     {
  218.         // this exception is not thrown
  219.     }
  220.     
  221.     return result;
  222. }
  223.  
  224.  
  225. /*----------------------------***  TOTALRESOURCES  ***---------------------------------*/
  226. /*
  227. how many resources are there altogether in this file?
  228. ---------------------------------------------------------------------------------------*/
  229.  
  230. short        ZResourceFile::TotalResources()
  231. {
  232.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  233.     
  234.     short    saveRes, num;
  235.     
  236.     SetResFork( &saveRes );
  237.     
  238.     num = Count1Types();
  239.     UseResFile( saveRes );
  240.     
  241.     return num;
  242. }
  243.  
  244.  
  245. /*----------------------------***  COUNTRESOURCES  ***---------------------------------*/
  246. /*
  247. how many resources of a given type are there in this file?
  248. ---------------------------------------------------------------------------------------*/
  249.  
  250. short        ZResourceFile::CountResources( const ResType aType )
  251. {
  252.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  253.     
  254.     short    saveRes, num;
  255.     
  256.     SetResFork( &saveRes );
  257.     
  258.     num = Count1Resources( aType );
  259.     UseResFile( saveRes );
  260.     
  261.     return num;
  262. }
  263.  
  264.  
  265. /*----------------------------***  GETRFATTRIBUTES  ***--------------------------------*/
  266. /*
  267. return the file attributes for this resource file
  268. ---------------------------------------------------------------------------------------*/
  269.  
  270. short        ZResourceFile::GetRFAttributes()
  271. {
  272.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  273.     
  274.     return GetResFileAttrs( resRefNum );
  275. }
  276.  
  277.  
  278. /*----------------------------***  GETRESOURCEINFO  ***--------------------------------*/
  279. /*
  280. get information about a resource (including the name)
  281. ---------------------------------------------------------------------------------------*/
  282.  
  283. void        ZResourceFile::GetResourceInfo(  Handle aResHandle, ResType* itsType, short* itsID, Str255 itsName )
  284. {
  285.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  286.     
  287.     GetResInfo( aResHandle, itsID, itsType, itsName );
  288. }
  289.  
  290.  
  291. /*----------------------------***  GETRESOURCEINFO  ***--------------------------------*/
  292. /*
  293. get information about a resource (not including the name)
  294. ---------------------------------------------------------------------------------------*/
  295.  
  296. void        ZResourceFile::GetResourceInfo(  Handle aResHandle, ResType* itsType, short* itsID )
  297. {
  298.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  299.     
  300.     Str255    itsName;
  301.     
  302.     GetResInfo( aResHandle, itsID, itsType, itsName );
  303. }
  304.  
  305.  
  306. /*-----------------------------***  WRITERESOURCE  ***---------------------------------*/
  307. /*
  308. add this handle to the resource file. If already part of this file, it is simply
  309. marked as modified and a subsequent flush or close will actually write it.
  310. ---------------------------------------------------------------------------------------*/
  311.  
  312. void        ZResourceFile::WriteResource( Handle aResHandle, const ResType aType, const short resID )
  313. {
  314.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  315.     
  316.     if ( OwnsResource( aResHandle ))
  317.         ResourceModified( aResHandle );
  318.     else
  319.     {
  320.         // we don't already own this resource, so we need to add a new one, or
  321.         // perhaps modify an existing one if it's there already.
  322.         
  323.         short    saveRes;
  324.         
  325.         SetResFork( &saveRes );
  326.         
  327.         short rID = ( resID == _UNIQUE_ID )? Unique1ID( aType ) : resID;
  328.         
  329.         try
  330.         {
  331.             if ( HasResource( aType, rID ))
  332.             {
  333.                 // does the type and ID already exist? If so we should remove it first
  334.         
  335.                 Handle    h = Get1Resource( aType, rID );
  336.                 
  337.                 if ( h )
  338.                 {
  339.                     RemoveResource( h );
  340.                     DisposeHandle( h );    
  341.                 }
  342.             }
  343.             
  344.             AddResource( aResHandle, aType, rID, "\p" );
  345.             FailOSErr( ResError());
  346.         }
  347.         catch( OSErr err )
  348.         {
  349.             UseResFile( saveRes );
  350.             
  351.             throw err;
  352.         }
  353.         
  354.         UseResFile( saveRes );
  355.     }
  356. }
  357.  
  358.  
  359. /*-----------------------------***  WRITERESOURCE  ***---------------------------------*/
  360. /*
  361. add this data to the resource file. This makes a new handle, or if the type and ID
  362. already exists, the new data replaces the old.
  363. ---------------------------------------------------------------------------------------*/
  364.  
  365. void        ZResourceFile::WriteResource( Ptr data, const long length, const ResType aType, const short resID )
  366. {
  367.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  368.     FailOSErr(( length < 0 )? paramErr : noErr );
  369.     FailOSErr(( data == NULL )? paramErr : noErr );
  370.     
  371.     // is there already a resource of the type indicated?
  372.     
  373.     short    saveRes, rID;
  374.     Handle    h;
  375.     
  376.     SetResFork( &saveRes );
  377.     
  378.     rID = ( resID == _UNIQUE_ID )? Unique1ID( aType ) : resID;
  379.     
  380.     try
  381.     {
  382.         if ( HasResource( aType, rID ))
  383.         {
  384.             // yes, we already have such a resource type, so modify it
  385.             
  386.             h = Get1Resource( aType, rID );
  387.             
  388.             if ( h )
  389.             {
  390.                 RemoveResource( h );
  391.                 DisposeHandle( h );    
  392.             }
  393.         }
  394.         // now add it
  395.         
  396.         FailNIL( h = NewHandle( length ));
  397.     
  398.         BlockMoveData( data, *h, length );
  399.         AddResource( h, aType, rID, "\p" );
  400.         FailOSErr( ResError());
  401.         
  402.         ReleaseResource( h );
  403.     }
  404.     catch( OSErr err )
  405.     {
  406.         UseResFile( saveRes );
  407.         
  408.         throw err;
  409.     }
  410.     
  411.     UseResFile( saveRes );
  412. }
  413.  
  414.  
  415. /*-----------------------------***  DELETERESOURCE  ***--------------------------------*/
  416. /*
  417. remove the resource from the file. This disposes the handle.
  418. ---------------------------------------------------------------------------------------*/
  419.  
  420. void        ZResourceFile::DeleteResource( Handle aResHandle )
  421. {
  422.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  423.     FailOSErr(( aResHandle == NULL )? paramErr : noErr );
  424.     
  425.     short    saveRes;
  426.     
  427.     SetResFork( &saveRes );
  428.     RemoveResource( aResHandle );
  429.     
  430.     try
  431.     {
  432.         FailOSErr( ResError());
  433.         DisposeHandle( aResHandle );
  434.     }
  435.     catch( OSErr err )
  436.     {
  437.         UseResFile( saveRes );
  438.         
  439.         throw err;
  440.     }
  441.     
  442.     UseResFile( saveRes );
  443. }
  444.  
  445. /*-----------------------------***  DELETERESOURCE  ***--------------------------------*/
  446. /*
  447. remove the resource of the given type and ID from the file.
  448. ---------------------------------------------------------------------------------------*/
  449.  
  450. void        ZResourceFile::DeleteResource( const ResType aType, const short resID )
  451. {
  452.     Handle        h;
  453.     
  454.     h = GetResource( aType, resID );
  455.     DeleteResource( h );
  456. }
  457.  
  458.  
  459. /*--------------------------------***  DELETEALL  ***----------------------------------*/
  460. /*
  461. remove all resources. This actually sets the length of the resource fork to zero
  462. ---------------------------------------------------------------------------------------*/
  463.  
  464. void        ZResourceFile::DeleteAll()
  465. {
  466.     // warning- use with extreme caution!
  467.     
  468.     Boolean        wasOpen = (resRefNum != _NOT_OPEN);
  469.     short        tempRef;
  470.     
  471.     if ( wasOpen )
  472.         CloseResFork();
  473.     
  474.     resRefNum = _NOT_OPEN;
  475.     
  476.     try
  477.     {    
  478.         // open the res fork as a fork without involving the resource manager,
  479.         // and set its length to zero.
  480.         
  481.         FailOSErr( FSpOpenRF( &itsSpec, fsCurPerm, &tempRef ));
  482.         FailOSErr( SetEOF( tempRef, 0 ));
  483.     }
  484.     catch( OSErr err )
  485.     {
  486.         FSClose( tempRef );
  487.         
  488.         throw err;
  489.     }
  490.     
  491.     FSClose( tempRef );
  492.     
  493.     // re-open the file with resource manager so that new map is built
  494.     
  495.     if ( wasOpen )
  496.         OpenResFork();
  497. }
  498.  
  499. /*-----------------------------***  RESOURCEMODIFIED  ***------------------------------*/
  500. /*
  501. the handle has been modified, mark it as such so the file is updated.
  502. ---------------------------------------------------------------------------------------*/
  503.  
  504. void        ZResourceFile::ResourceModified( Handle aResHandle )
  505. {
  506.     ChangedResource( aResHandle );
  507.     FailOSErr( ResError());
  508.     
  509.     // inhibit purging for this handle, so it gets written
  510.     // correctly later on.
  511.     
  512.     HNoPurge( aResHandle );
  513. }
  514.  
  515. /*----------------------------------***  FLUSH  ***------------------------------------*/
  516. /*
  517. write out all changed resources to the disk, leaving the file open. Close will do this
  518. as well, then close the file.
  519. ---------------------------------------------------------------------------------------*/
  520.  
  521. void        ZResourceFile::Flush()
  522. {
  523.     FailOSErr(( resRefNum == _NOT_OPEN )? resFNotFound : noErr );
  524.     
  525.     UpdateResFile( resRefNum );
  526. }
  527.  
  528.     
  529.